package com.csii.activiti.server.core.utils;

import org.apache.commons.lang3.RandomUtils;

import java.util.HashSet;
import java.util.Set;

public class ShortUUID {
    /**
     * digits还可以扩,但是不要包含下面的SEPARATOR
     * <p>
     * <p>
     * <p>
     * 也可以替换一个"乱序"digits排列,最终使uuid看起来不是有序的.
     * <p>
     * <p>
     * <p>
     * 一旦用到生产环境,digits就不要再变动了,否则会出现重复
     */

    private static final char[] DIGITS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"

            .toCharArray();

    private static final char SEPARATOR = '_';

    // 2019-11-15 17:00:00

    private static final long ERA_TIME = 1573808400000L;

    // UUID一次轮回的指数. 12则为大概30年左右,11则为3年左右. 13就是300年

    private static final int TIME_LOOP_INDEX = 12;

    // 碰撞指数.毫秒下万万分之一

    private static final int COLLISION_INDEX = 99999999;

    private static final boolean MIX_UP = true;

    public static String randomUUID() {
        long passTime = System.currentTimeMillis() - ERA_TIME;

        long l = passTime;

        // 反转主要是为了让uuid看起来不是递增的

        // 但这也会导致出现极小概率不同时间的碰撞,所以建议优先选择不反转

        if (MIX_UP) {
            StringBuilder stringBuilder = new StringBuilder(String.valueOf(passTime)).reverse();

            while (stringBuilder.length() < TIME_LOOP_INDEX) {
                stringBuilder.append('0');

            }

            l = Long.parseLong(stringBuilder.substring(0, TIME_LOOP_INDEX));

        }

        return baseConversion(l, DIGITS.length) + SEPARATOR +

                baseConversion(RandomUtils.nextInt(0,COLLISION_INDEX), DIGITS.length);

    }

    public static void main(String[] args) throws InterruptedException {
        Set<String> set = new HashSet<>();
        for (int i = 0; i < 100000; i++) {
            String arg = randomUUID();
            if (set.contains(arg)){
                System.out.println("重复了");
            }else{
                set.add(arg);
            }
        }
    }

    /**
     * 将10进制转换成任意进制,照着Long原生的进制转换写的,原生最大支持到32进制
     * <p>
     * <p>
     * <p>
     * 这里支持到更高进制,可以扩展digits数组实现更高
     *
     * @param i     十进制Long型
     * @param radix 进制,[2-62]
     * @return 转换后的String
     */

    public static String baseConversion(long i, int radix) {
        if (radix < 2 || radix > DIGITS.length) {
            radix = 10;

        }

        int charPos = DIGITS.length * 2;

        final int size = charPos + 1;

        char[] buf = new char[size];

        boolean negative = (i < 0);

        if (!negative) {
            i = -i;

        }

        while (i <= -radix) {
            buf[charPos--] = DIGITS[(int) (-(i % radix))];

            i = i / radix;

        }

        buf[charPos] = DIGITS[(int) (-i)];

        if (negative) {
            buf[--charPos] = '-';

        }

        return new String(buf, charPos, (size - charPos));

    }

}
